package com.czarea.pay.sdk.wxpay.response;

import com.google.common.collect.Lists;
import com.thoughtworks.xstream.annotations.XStreamAlias;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * 退款查询
 *
 * @author zhouzx
 */
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@XStreamAlias("xml")
public class WxPayRefundQueryResponse extends WxPayBaseResponse {

    /**
     * <pre> 设备号 device_info 否 String(32) 013467007045764 终端设备号
     */
    @XStreamAlias("device_info")
    private String deviceInfo;

    /**
     * <pre> 微信订单号 transaction_id 是 String(32) 1217752501201407033233368018 微信订单号
     */
    @XStreamAlias("transaction_id")
    private String transactionId;

    /**
     * <pre> 商户订单号 out_trade_no 是 String(32) 1217752501201407033233368018 商户系统内部的订单号
     */
    @XStreamAlias("out_trade_no")
    private String outTradeNo;

    /**
     * <pre> 订单金额 total_fee 是 Int 100 订单总金额，单位为分，只能为整数，详见支付金额
     */
    @XStreamAlias("total_fee")
    private Integer totalFee;

    /**
     * <pre> 应结订单金额 settlement_total_fee 否 Int 100 应结订单金额=订单金额-非充值代金券金额，应结订单金额<=订单金额。
     */
    @XStreamAlias("settlement_total_fee")
    private Integer settlementTotalFee;

    /**
     * <pre> 货币种类 fee_type 否 String(8) CNY 订单金额货币类型，符合ISO 4217标准的三位字母代码，默认人民币：CNY，其他值列表详见货币类型
     */
    @XStreamAlias("fee_type")
    private String feeType;

    /**
     * <pre> 现金支付金额 cash_fee 是 Int 100 现金支付金额，单位为分，只能为整数，详见支付金额
     */
    @XStreamAlias("cash_fee")
    private Integer cashFee;

    /**
     * <pre> 退款笔数 refund_count 是 Int 1 退款记录数
     */
    @XStreamAlias("refund_count")
    private Integer refundCount;

    private List<RefundRecord> refundRecords;

    /**
     * 组装生成退款记录属性的内容
     */
    public void composeRefundRecords() {
        if (this.refundCount != null && this.refundCount > 0) {
            this.refundRecords = Lists.newArrayList();

            for (int i = 0; i < this.refundCount; i++) {
                RefundRecord refundRecord = new RefundRecord();
                this.refundRecords.add(refundRecord);

                refundRecord.setOutRefundNo(this.getXmlValue("xml/out_refund_no_" + i));
                refundRecord.setRefundId(this.getXmlValue("xml/refund_id_" + i));
                refundRecord.setRefundChannel(this.getXmlValue("xml/refund_channel_" + i));
                refundRecord.setRefundFee(this.getXmlValueAsInt("xml/refund_fee_" + i));
                refundRecord.setSettlementRefundFee(
                    this.getXmlValueAsInt("xml/settlement_refund_fee_" + i));
                refundRecord.setCouponType(this.getXmlValue("xml/coupon_type_" + i));
                refundRecord
                    .setCouponRefundFee(this.getXmlValueAsInt("xml/coupon_refund_fee_" + i));
                refundRecord.setCouponRefundCount(
                    this.getXmlValueAsInt("xml/coupon_refund_count_" + i));
                refundRecord.setRefundStatus(this.getXmlValue("xml/refund_status_" + i));
                refundRecord.setRefundRecvAccount(this.getXmlValue("xml/refund_recv_accout_" + i));

                if (refundRecord.getCouponRefundCount() == null
                    || refundRecord.getCouponRefundCount() == 0) {
                    continue;
                }

                List<RefundRecord.RefundCoupon> coupons = Lists.newArrayList();
                for (int j = 0; j < refundRecord.getCouponRefundCount(); j++) {
                    coupons.add(new RefundRecord.RefundCoupon(
                        this.getXmlValue("xml/coupon_refund_id_" + i + "_" + j),
                        this.getXmlValueAsInt("xml/coupon_refund_fee_" + i + "_" + j)));
                }
            }

        }
    }

    @Data
    @Builder(builderMethodName = "newBuilder")
    @NoArgsConstructor
    @AllArgsConstructor
    public static class RefundRecord {

        /**
         * <pre>
         * 商户退款单号
         * out_refund_no_$n
         * 是
         * String(32)
         * 1217752501201407033233368018
         * 商户退款单号
         * </pre>
         */
        @XStreamAlias("out_refund_no")
        private String outRefundNo;

        /**
         * <pre>
         * 微信退款单号
         * refund_id_$n
         * 是
         * String(28)
         * 1217752501201407033233368018
         * 微信退款单号
         * </pre>
         */
        @XStreamAlias("refund_id")
        private String refundId;

        /**
         * <pre>
         * 退款渠道
         * refund_channel_$n
         * 否
         * String(16)
         * ORIGINAL
         * ORIGINAL—原路退款 BALANCE—退回到余额
         * </pre>
         */
        @XStreamAlias("refund_channel")
        private String refundChannel;

        /**
         * <pre>
         * 申请退款金额
         * refund_fee_$n
         * 是
         * Int
         * 100
         * 退款总金额,单位为分,可以做部分退款
         * </pre>
         */
        @XStreamAlias("refund_fee")
        private Integer refundFee;

        /**
         * <pre>
         * 退款金额
         * settlement_refund_fee_$n
         * 否
         * Int
         * 100
         * 退款金额=申请退款金额-非充值代金券退款金额，退款金额<=申请退款金额
         * </pre>
         */
        @XStreamAlias("settlement_refund_fee")
        private Integer settlementRefundFee;

        /**
         * <pre>
         * 退款资金来源
         * refund_account
         * 否
         * String(30)
         * REFUND_SOURCE_RECHARGE_FUNDS
         * REFUND_SOURCE_RECHARGE_FUNDS---可用余额退款/基本账户, REFUND_SOURCE_UNSETTLED_FUNDS---未结算资金退款
         * </pre>
         */
        @XStreamAlias("refund_account")
        private String refundAccount;

        /**
         * <pre>
         * 代金券类型
         * coupon_type_$n
         * 否
         * Int
         * CASH
         * CASH--充值代金券 , NO_CASH---非充值代金券。订单使用代金券时有返回（取值：CASH、NO_CASH）。$n为下标,从0开始编号，举例：coupon_type_$0
         * </pre>
         */
        @XStreamAlias("coupon_type")
        private String couponType;

        /**
         * <pre>
         * 代金券退款金额
         * coupon_refund_fee_$n
         * 否
         * Int
         * 100
         * 代金券退款金额<=退款金额，退款金额-代金券或立减优惠退款金额为现金，说明详见代金券或立减优惠
         * </pre>
         */
        @XStreamAlias("coupon_refund_fee")
        private Integer couponRefundFee;

        /**
         * <pre>
         * 退款代金券使用数量
         * coupon_refund_count_$n
         * 否
         * Int
         * 1
         * 退款代金券使用数量 ,$n为下标,从0开始编号
         * </pre>
         */
        @XStreamAlias("coupon_refund_count")
        private Integer couponRefundCount;

        private List<RefundCoupon> refundCoupons;

        /**
         * <pre>
         * 退款状态
         * refund_status_$n
         * 是
         * String(16)
         * SUCCESS
         * 退款状态：
         *  SUCCESS—退款成功，
         *  FAIL—退款失败，
         *  PROCESSING—退款处理中，
         *  CHANGE—转入代发，
         * 退款到银行发现用户的卡作废或者冻结了，导致原路退款银行卡失败，资金回流到商户的现金帐号，需要商户人工干预，通过线下或者财付通转账的方式进行退款。
         * </pre>
         */
        @XStreamAlias("refund_status")
        private String refundStatus;
        /**
         * <pre>
         * 退款入账账户
         * refund_recv_accout_$n
         * 是
         * String(64)
         * 招商银行信用卡0403
         * 取当前退款单的退款入账方，1）退回银行卡：{银行名称}{卡类型}{卡尾号}，2）退回支付用户零钱:支付用户零钱
         * </pre>
         */
        @XStreamAlias("refund_recv_accout")
        private String refundRecvAccount;

        @Data
        @NoArgsConstructor
        public static class RefundCoupon {

            /**
             * <pre>
             * 退款代金券批次ID
             * coupon_refund_batch_id_$n_$m
             * 否
             * String(20)
             * 100
             * 退款代金券批次ID ,$n为下标，$m为下标，从0开始编号
             * </pre>
             *
             * @deprecated 貌似是被去掉了，但不知是何时！
             */
            @XStreamAlias("coupon_refund_batch_id")
            private String couponRefundBatchId;

            /**
             * <pre>
             * 退款代金券ID
             * coupon_refund_id_$n_$m
             * 否
             * String(20)
             * 10000
             * 退款代金券ID, $n为下标，$m为下标，从0开始编号
             * </pre>
             */
            @XStreamAlias("coupon_refund_id")
            private String couponRefundId;

            /**
             * <pre>
             * 单个退款代金券支付金额
             * coupon_refund_fee_$n_$m
             * 否
             * Int
             * 100
             * 单个退款代金券支付金额, $n为下标，$m为下标，从0开始编号
             * </pre>
             */
            @XStreamAlias("coupon_refund_fee")
            private Integer couponRefundFee;

            public RefundCoupon(String couponRefundId, Integer couponRefundFee) {
                this.couponRefundId = couponRefundId;
                this.couponRefundFee = couponRefundFee;
            }

        }

    }

}

